﻿using System.Runtime.InteropServices;

namespace FZRD
{
    class FileUnlocker
    {
        [DllImport("kernel32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        static extern bool CloseHandle(IntPtr hObject);

        [DllImport("kernel32.dll")]
        static extern IntPtr CreateFile(
            string lpFileName,
            uint dwDesiredAccess,
            uint dwShareMode,
            IntPtr lpSecurityAttributes,
            uint dwCreationDisposition,
            uint dwFlagsAndAttributes,
            IntPtr hTemplateFile);

        [DllImport("kernel32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        static extern bool DeviceIoControl(
            IntPtr hDevice,
            uint dwIoControlCode,
            IntPtr lpInBuffer,
            uint nInBufferSize,
            IntPtr lpOutBuffer,
            uint nOutBufferSize,
            ref uint lpBytesReturned,
            IntPtr lpOverlapped);

        /// INVALID_HANDLE_VALUE -> -1   
        private const int INVALID_HANDLE_VALUE = -1;
        /// GENERIC_READ -> (0x80000000L)   
        private const uint GENERIC_READ = 0x80000000;
        /// GENERIC_WRITE -> (0x40000000L)   
        private const uint GENERIC_WRITE = 0x40000000;
        /// FILE_SHARE_READ -> 0x00000001   
        private const int FILE_SHARE_READ = 0x00000001;
        /// FILE_SHARE_WRITE -> 0x00000002   
        private const int FILE_SHARE_WRITE = 0x00000002;
        /// OPEN_EXISTING -> 0x00000011   
        private const int OPEN_EXISTING = 0x00000011;


        private const int FILE_DEVICE_FILE_SYSTEM = 0x00000009;
        private const int METHOD_BUFFERED = 0;
        private const int FILE_ANY_ACCESS = 0;

        private const int FSCTL_LOCK_VOLUME = ((FILE_DEVICE_FILE_SYSTEM) << 16) | ((FILE_ANY_ACCESS) << 14) | ((6) << 2) | (METHOD_BUFFERED);//0x00090018;
        private const int FSCTL_UNLOCK_VOLUME = ((FILE_DEVICE_FILE_SYSTEM) << 16) | ((FILE_ANY_ACCESS) << 14) | ((7) << 2) | (METHOD_BUFFERED);//0x0009001C;
        private const int FSCTL_DISMOUNT_VOLUME = ((FILE_DEVICE_FILE_SYSTEM) << 16) | ((FILE_ANY_ACCESS) << 14) | ((8) << 2) | (METHOD_BUFFERED);//0x00090020;

        private const int FILE_DEVICE_MASS_STORAGE = 0x0000002d;
        private const int IOCTL_STORAGE_BASE = FILE_DEVICE_MASS_STORAGE;
        private const int FILE_READ_ACCESS = 0x0001;// file & pipe


        public static bool UnlockFile(string filePath)
        {
            IntPtr fileHandle = CreateFile(filePath, GENERIC_READ, FILE_SHARE_READ, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero);
            if (fileHandle == IntPtr.Zero || fileHandle == new IntPtr(INVALID_HANDLE_VALUE))
            {
                return false;
            }

            uint bytesReturned = 0;
            bool result = DeviceIoControl(fileHandle, FSCTL_UNLOCK_VOLUME, IntPtr.Zero, 0, IntPtr.Zero, 0, ref bytesReturned, IntPtr.Zero);
            CloseHandle(fileHandle);
            return result;
        }
    }
}